package com.ruyuan.commodity.consumer.service;

import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;
import java.io.IOException;

/**
 * 将静态页存储到redis的操作
 */
@Component
public class PageCreatorServiceImpl implements PageCreatorService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 请求成功的状态码
     */
    private static final int SUCCESS = 200;

    /**
     * 静态页地址
     */
    @Value("${ruyuan.staticAddress}")
    private String staticAddress;
    /**
     * redis缓存模板
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 生成一个静态页
     * @param path  页面地址
     * @param type  客户端类型
     * @param name  生成静态页面在redis中的key
     * @throws Exception 异常信息
     */
    @Override
    public void createOne(String path, String type, String name) throws Exception {
        // 生成消息
        String url = getStaticUrl(path);
        // 通过http 来获取html存储redis
        String html = this.getHtmlByGoodsId(url, type);
        stringRedisTemplate.opsForValue().set(name, html);
    }

    /**
     * 传入url 返回对应页面的html
     *
     * @param url  页面的url
     * @param type 客户端类型
     * @return 返回对应页面的html
     * @throws ClientProtocolException 异常信息
     * @throws IOException 异常信息
     */
    private String getHtmlByGoodsId(String url, String type) throws IOException {
        // 重试次数
        int retryTimes = 10;
        return getHtml(url, type, retryTimes);
    }

    /**
     * 将商品详情页的HTML缓存到Redis
     * @param url 静态页地址
     * @param type 静态页类型
     * @param retryTimes 重试次数
     * @return 静态页HTML
     * @throws IOException io异常信息
     */
    private String getHtml(String url, String type, int retryTimes) throws IOException {
        String html;
        // socket超时  connect超时
        RequestConfig requestConfig = RequestConfig.custom()
                .setSocketTimeout(50000)
                .setConnectTimeout(50000)
                .build();
        CloseableHttpResponse response = null;
        try {
            CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfig).build();
            HttpGet httpGet = new HttpGet(url);
            httpGet.setHeader("Client-Type", type);
            response = httpClient.execute(httpGet);
            retryTimes--;
        } catch (Exception e) {
            retryTimes--;
            logger.error("获取 [{}] 详情页数据时，发生异常", url, e);
        }

        if (!ObjectUtils.isEmpty(response)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == SUCCESS) {
                html = EntityUtils.toString(response.getEntity(), "utf-8");
                return html;
            }

            while (retryTimes > 0) {
                logger.info("进入重试获取详情页的逻辑 url地址为 [{}] 当前重试次数为 [{}]", url, retryTimes);
                try {
                    Thread.sleep(retryTimes * 1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                html = getHtml(url, type, retryTimes);
                return html;
            }
        }
        return "";
    }


    /**
     * 获取url
     *
     * @param path 路径
     * @return url
     */
    private String getStaticUrl(String path) {
        if (staticAddress.endsWith("/")) {
            staticAddress = staticAddress.substring(0, staticAddress.length() - 1);
        }
        return staticAddress + path;
    }

}
